home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / src / fdtolib / fdtolib.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-09-09  |  20.8 KB  |  1,025 lines

  1. /*
  2.  *    (c)Copyright 1992-1997 Obvious Implementations Corp.  Redistribution and
  3.  *    use is allowed under the terms of the DICE-LICENSE FILE,
  4.  *    DICE-LICENSE.TXT.
  5.  */
  6. /*
  7.  *    (c)Copyright 1992-1997 Obvious Implementations Corp.  Redistribution and
  8.  *    use is allowed under the terms of the DICE-LICENSE FILE,
  9.  *    DICE-LICENSE.TXT.
  10.  */
  11.  
  12. /*
  13.  *  FDTOLIB.C
  14.  *
  15.  *  FDTOLIB fdfile[s] [-h hdrfile] -o libname [-mr] [-mD] [-pprefix] -I incldir
  16.  *            -prof -mc -mC -auto libname -AUTO libname
  17.  *
  18.  *  Generates a normal model or registerized modem library interface given
  19.  *  any set of FD files.
  20.  *
  21.  *  -ms, -r, and -pr are ignored
  22.  */
  23.  
  24. #ifdef AMIGA
  25. #include <exec/types.h>
  26. #include <exec/nodes.h>
  27. #include <exec/lists.h>
  28. #include <clib/exec_protos.h>
  29. #include <clib/dos_protos.h>
  30. #include <clib/alib_protos.h>
  31. #include <lib/profile.h>
  32. #include <lib/version.h>
  33. #else
  34. #include <include/lib/profile.h>
  35. #include <include/lib/version.h>
  36. #endif
  37.  
  38. #include <stdio.h>
  39. #include <stdlib.h>
  40. #include <string.h>
  41.  
  42. #ifndef AMIGA
  43. #include <suplib/all.h>
  44. #endif
  45.  
  46. #ifndef L_tmpnam
  47. #define L_tmpnam    64
  48. #endif
  49.  
  50. #define RF_SCRATCH  0x0303
  51. #define RB_BP        (8+6)
  52. #define RF_BP        (1 << RB_BP)
  53.  
  54. IDENT("fdtolib", ".5");
  55. DCOPYRIGHT;
  56.  
  57. typedef unsigned short uword;
  58. typedef struct List    List;
  59. typedef struct Node    Node;
  60.  
  61. typedef struct LVONode {
  62.     Node    lv_Node;
  63.     short   lv_Offset;
  64. } LVONode;
  65.  
  66. typedef struct RSNode {
  67.     Node    rn_Node;
  68.     short   rn_Args;        /*    -1 specifies stack  */
  69.     short   rn_Flag;        /*    equiv/fd found        */
  70.     short   rn_Regs[32];    /*    transfer registers  */
  71. } RSNode;
  72.  
  73. void    help(int);
  74. void    ScanFD(FILE *, FILE *);
  75. void    ScanRSTmp(FILE *);
  76. void    GenerateFunction(FILE *, char *, char *, int);
  77. int    AssembleFile(char *, char *);
  78. void    JoinOutput(FILE *, char *);
  79. char    *RegMaskToStr(uword, short *);
  80. uword    RegsToMask(short *, short);
  81. char    *RegToStr(short);
  82. void    RegsCall(FILE *, char *, long, RSNode *, short *);
  83. void    StackCall(FILE *, char *, long, short *, short);
  84. short    PushMask(FILE *, uword);
  85. short    PopMask(FILE *, uword);
  86. void    AddLVOList(char *, int);
  87. void    GenerateLVOList(FILE *);
  88. void    GenerateAutoOpen(FILE *, char *);
  89. void    DicePrefix(char *, char *, char *);
  90.  
  91. List    FDList;     /*  list of FD files   */
  92. List    RSList;     /*  register spec list */
  93. List    LVOList;
  94. char    DccOptsBuf[1024];
  95. char    *OutFile;
  96. char    *HdrFile;
  97. char    *FuncPrefix = "_";
  98. char    Buf[256];
  99. char    FuncName[256];
  100. char    Prefix[64];
  101. short    RegOpt;
  102. short    Verbose;
  103. short    Symbols = 1;
  104. short    SmallData = 1;
  105. short    SmallCode = 1;
  106. short    ProfOpt;
  107. short    AutoOpt;
  108. char    *DataModel = "(A4)";
  109. char    *CodeModel = "(PC)";
  110. char    *SharedLibName;
  111.  
  112. int
  113. main(int ac, char **av)
  114. {
  115.     int i;
  116.  
  117.     NewList(&FDList);
  118.     NewList(&RSList);
  119.     NewList(&LVOList);
  120.  
  121.     DicePrefix(Prefix, av[0], "");
  122.  
  123. #ifndef LATTICE
  124. #ifndef unix
  125.     expand_args(ac, av, &ac, &av);
  126. #endif
  127. #else
  128.     setbuf(stdout, NULL);
  129. #endif
  130.  
  131.     for (i = 1; i < ac; ++i) {
  132.     char *ptr = av[i];
  133.  
  134.     if (*ptr != '-') {
  135.         Node *node = malloc(sizeof(Node));
  136.         node->ln_Name = ptr;
  137.         AddTail(&FDList, node);
  138.         continue;
  139.     }
  140.     ptr += 2;
  141.     switch(ptr[-1]) {
  142.     case 'a':
  143.         AutoOpt = 1;
  144.         SharedLibName = av[++i];
  145.         break;
  146.     case 'A':
  147.         AutoOpt = 2;
  148.         SharedLibName = av[++i];
  149.         break;
  150.     case 'p':
  151.         if (strcmp(ptr, "rof") == 0)
  152.         ProfOpt = 1;
  153.         else if (strcmp(ptr, "r") == 0)     /*  ignore -pr  */
  154.         ;
  155.         else
  156.         FuncPrefix = (*ptr) ? ptr : av[++i];
  157.         break;
  158.     case 'o':
  159.         OutFile = (*ptr) ? ptr : av[++i];
  160.         break;
  161.     case 'h':
  162.         HdrFile = (*ptr) ? ptr : av[++i];
  163.         break;
  164.     case 'm':
  165.         if (*ptr == 'r' || *ptr == 'R')
  166.         RegOpt = 1;
  167.         else if (*ptr == 'd') {
  168.         SmallData = 1;
  169.         DataModel = "(A4)";
  170.         } else if (*ptr == 'D') {
  171.         SmallData = 0;
  172.         DataModel = "";
  173.         } else if (*ptr == 'c') {
  174.         SmallCode = 1;
  175.         CodeModel = "(pc)";
  176.         } else if (*ptr == 'C') {
  177.         SmallCode = 0;
  178.         CodeModel = "";
  179.         } else if (*ptr == 's') {
  180.         /*  ignore  */
  181.         }
  182.         break;
  183.     case 'r':
  184.         /* ignore -r    */
  185.         break;
  186.     case 'v':
  187.         ++Verbose;
  188.         break;
  189.     case 'I':
  190.         sprintf(DccOptsBuf + strlen(DccOptsBuf), " -I%s", (*ptr) ? ptr : av[++i]);
  191.         break;
  192.  
  193.     case 'n':
  194.         Symbols = 0;
  195.         break;
  196.  
  197.     default:
  198.         help(1);
  199.     }
  200.     }
  201.     if (OutFile == NULL || (RegOpt && HdrFile == NULL))
  202.     help(ac != 1);
  203.  
  204.     if (RegOpt == 0 && HdrFile)
  205.     puts("Warning: header file ignored (used only with -mr)");
  206.  
  207.     /*
  208.      *    step 2, ask DCC to generate a register specification file
  209.      */
  210.  
  211.     if (RegOpt) {
  212.     FILE *fi;
  213.     char rs_tmp[L_tmpnam];
  214.  
  215.     sprintf(Buf, "%sdcc -mRRX %s -a -o %s%s",
  216.         Prefix,
  217.         HdrFile,
  218.         tmpnam(rs_tmp),
  219.         DccOptsBuf
  220.     );
  221.     if(Symbols)strcat(Buf," -s -sym");
  222.     puts(Buf);
  223. #ifdef unix
  224.         system(Buf);
  225. #else
  226.     Execute(Buf, NULL, NULL);
  227. #endif
  228.  
  229.     if ((fi = fopen(rs_tmp, "r")) == NULL) {
  230.         puts("Unable to generate register specification file");
  231.         help(20);
  232.     }
  233.     ScanRSTmp(fi);
  234.     fclose(fi);
  235.     remove(rs_tmp);
  236.     }
  237.  
  238.     /*
  239.      *    step 3
  240.      */
  241.  
  242.  
  243.     {
  244.     FILE *fi;
  245.     FILE *fo = fopen(OutFile, "w");
  246.     Node *node;
  247.  
  248.     if (fo == NULL) {
  249.         printf("Error, Unable to create %s\n", OutFile);
  250.         exit(20);
  251.     }
  252.     while ((node = RemHead(&FDList)) != NULL) {
  253.         printf("generate %s", node->ln_Name);
  254.         fi = fopen(node->ln_Name, "r");
  255.         if (fi) {
  256.         puts("");
  257.         ScanFD(fi, fo);
  258.         fclose(fi);
  259.         } else {
  260.         puts(" (open failed)");
  261.         }
  262.     }
  263.     }
  264.     {
  265. #ifdef NOTDEF
  266.     RSNode *rs;
  267.  
  268.     for (rs = RSList.lh_Head; rs->rn_Node.ln_Succ; rs = (RSNode *)rs->rn_Node.ln_Succ) {
  269.         if (rs->rn_Flag == 0)
  270.         printf("Warning, no FD entry found for: %s\n", rs->rn_Node.ln_Name);
  271.     }
  272. #endif
  273.     }
  274.     return(0);
  275. }
  276.  
  277. void
  278. help(int code)
  279. {
  280.     puts(Ident);
  281.     puts(DCopyright);
  282.     puts("FDTOLIB files/wildcard [-h hdrfile] -o libname [-mr] [-mD]");
  283.     puts("  -mr :   generate registered library from header & fd file");
  284.     puts("  -mD :   large data model (else small data model)");
  285.     exit(code);
  286. }
  287.  
  288. void
  289. ScanFD(fi, fo)
  290. FILE *fi;
  291. FILE *fo;
  292. {
  293.     char *base = NULL;
  294.     long bias = -1;
  295.     short end = 0;
  296.     short public = 1;
  297.  
  298.     char *key;
  299.  
  300.     while (fgets(Buf, sizeof(Buf), fi)) {
  301.     if (Buf[0] == '\n' || Buf[0] == '*')
  302.         continue;
  303.     if (strncmp(Buf, "##", 2) != 0) {
  304.         if (bias < 0 || base == NULL) {
  305.         printf("Error, No ##base/##bias before function: %s\n", Buf);
  306.         continue;
  307.         }
  308.         if (public && AutoOpt != 2)
  309.         GenerateFunction(fo, Buf, base, bias);
  310.         bias += 6;
  311.         continue;
  312.     }
  313.     if ((key = strtok(Buf + 2, " \t\n")) == NULL) {
  314.         printf("\tError, Illegal null directive\n");
  315.         continue;
  316.     }
  317.     if (stricmp(key, "base") == 0) {
  318.         if ((key = strtok(NULL, " \t\n")) != NULL) {
  319.         if (base)
  320.             free(base);
  321.         base = strdup(key);
  322.         } else {
  323.         printf("\tError, Illegal ##base directive\n");
  324.         }
  325.         continue;
  326.     }
  327.     if (stricmp(key, "bias") == 0) {
  328.         if ((key = strtok(NULL, " \t\n")) != NULL) {
  329.         char *dummy;
  330.  
  331.         bias = strtol(key, &dummy, 0);
  332.         if (bias <= 0)
  333.             printf("\tError, Illegal ##bias: %ld\n", bias);
  334.         } else {
  335.         printf("\tError, Illegal ##bias directive\n");
  336.         }
  337.         continue;
  338.     }
  339.     if (stricmp(key, "public") == 0) {
  340.         public = 1;
  341.         continue;
  342.     }
  343.     if (stricmp(key, "private") == 0) {
  344.         public = 0;
  345.         continue;
  346.     }
  347.     if (stricmp(key, "end") == 0) {
  348.         end = 1;
  349.         break;
  350.     }
  351.     printf("\tError, Unrecognized directive: %s\n", key);
  352.     }
  353.     if (bias < 0)
  354.     puts("\tUnexpected EOF, no ##bias");
  355.     if (base == NULL)
  356.     puts("\tUnexpected EOF, no ##base");
  357.     if (end == 0)
  358.     puts("\tUnexpected EOF, no ##end directive");
  359.     if (AutoOpt != 2)
  360.     GenerateLVOList(fo);
  361.     if (AutoOpt)
  362.     GenerateAutoOpen(fo, base);
  363. }
  364.  
  365. /*
  366.  *  funcname(var,var,var)(reg,reg,reg)        (or reg/reg)
  367.  */
  368.  
  369. static short    FRegs[128];
  370.  
  371. void
  372. GenerateFunction(fo, buf, base, bias)
  373. FILE *fo;
  374. char *buf;
  375. char *base;
  376. int bias;
  377. {
  378.     char tmpFile[L_tmpnam];
  379.     char objFile[L_tmpnam+4];
  380.     char *funcName;
  381.     FILE *ft;
  382.     short argCnt;
  383.     short noArgs = 0;
  384.  
  385.     funcName = buf;
  386.     while (*funcName && *funcName != '\t' && *funcName != ' ' && *funcName != '(')
  387.     ++funcName;
  388.     if (*funcName == ' ' || *funcName == '\t') {
  389.     while (*funcName && *funcName != '(')
  390.         *funcName++ = 0;
  391.     }
  392.     if (*funcName == '(') {
  393.     *funcName++ = 0;
  394.     if (*funcName == ')')
  395.         noArgs = 1;
  396.     }
  397.     while (*funcName && *funcName != ')')   /*  skip text args  */
  398.     ++funcName;
  399.     while (*funcName && *funcName != '(')
  400.     ++funcName;
  401.     if (noArgs == 0 && *funcName == 0) {
  402.     printf("\tError in line: %s\n", buf);
  403.     return;
  404.     }
  405.  
  406.     /*
  407.      *    get register description
  408.      */
  409.  
  410.     if (*funcName)
  411.     ++funcName;
  412.     for (argCnt = 0; *funcName && *funcName != '\n' && *funcName != ')'; ++argCnt) {
  413.     switch(*funcName) {
  414.     case 'd':
  415.     case 'D':
  416.         FRegs[argCnt] = *++funcName - '0';
  417.         ++funcName;
  418.         break;
  419.     case 'a':
  420.     case 'A':
  421.         FRegs[argCnt] = *++funcName - '0' + 8;
  422.         ++funcName;
  423.         break;
  424.     default:
  425.         printf("\tError in register spec: %s\n", funcName);
  426.         return;
  427.     }
  428.     if (*funcName == ',' || *funcName == '/')
  429.         ++funcName;
  430.     }
  431.     if (noArgs == 0 && *funcName != ')') {
  432.     printf("\tError in register spec: %s\n", funcName);
  433.     return;
  434.     }
  435.  
  436.     /*
  437.      *    generate
  438.      */
  439.  
  440.     funcName = strdup(buf);
  441.     {
  442.     RSNode *rs = NULL;
  443.  
  444.     if (Verbose)
  445.         printf("    %-15s %d %d ", funcName, -bias, argCnt);
  446.  
  447.     if (RegOpt) {
  448.         for (rs = (RSNode *)RSList.lh_Head; rs->rn_Node.ln_Succ; rs = (RSNode *)rs->rn_Node.ln_Succ) {
  449.         if (strcmp(rs->rn_Node.ln_Name + 1, funcName) == 0) {
  450.             rs->rn_Flag = 1;
  451.             break;
  452.         }
  453.         }
  454.         if (rs->rn_Node.ln_Succ == NULL) {    /* (list tail)    */
  455.         if (Verbose)
  456.             puts("NO MATCH FOUND");
  457.         return;
  458.         }
  459.  
  460.         if (rs->rn_Args >= 0 && rs->rn_Args != argCnt) {
  461.         printf("Error, argCnt mismatch %s (%d/%d)\n", rs->rn_Node.ln_Name, rs->rn_Args, argCnt);
  462.         return;
  463.         }
  464.     }
  465.     if (Verbose)
  466.         fflush(stdout);
  467.  
  468.     tmpnam(tmpFile);
  469.     sprintf(objFile, "%s.o", tmpFile);
  470.  
  471.     if (RegOpt)
  472.         sprintf(FuncName, "%s", rs->rn_Node.ln_Name);
  473.     else
  474.         sprintf(FuncName, "%s%s", FuncPrefix, funcName);
  475.  
  476.     if ((ft = fopen(tmpFile, "w")) != NULL) {
  477.         if (ProfOpt) {
  478.         fprintf(ft, "\txref\t__ProfInit\n");
  479.         fprintf(ft, "\txref\t__ProfExec\n");
  480.  
  481.         fprintf(ft, "\n\tsection autoinit1,code\n");
  482.         fprintf(ft, "\tlea\tlp0%s,A0\n", DataModel);
  483.         fprintf(ft, "\tjsr\t__ProfInit\n");
  484.         fprintf(ft, "\n\tsection libdata,data\n");
  485.         fprintf(ft, "\tds.l\t0\n");
  486.         fprintf(ft, "lp0\n");
  487.         fprintf(ft, "\tdc.l\t0\n");
  488.         fprintf(ft, "\tdc.l\t0\n");
  489.         fprintf(ft, "\tdc.l\t0\n");
  490.         fprintf(ft, "\tdc.w\t%d\n", (40 + strlen(FuncName) + (1 + 3)) & ~3);
  491.         fprintf(ft, "\tdc.w\t0\n");
  492.         fprintf(ft, "\tdc.l\t0\n");
  493.         fprintf(ft, "\tdc.l\t0\n");
  494.         fprintf(ft, "\tdc.l\t0\n");
  495.         fprintf(ft, "\tdc.l\t0\n");
  496.         fprintf(ft, "\tdc.l\tlp1\n");
  497.         fprintf(ft, "\tdc.l\tlp2\n");
  498.         fprintf(ft, "\tdc.b\t\'%s\',0\n", FuncName);
  499.  
  500.         fprintf(ft, "\tds.l\t0\n");
  501.         }
  502.         fprintf(ft, "\n\tsection ,code\n\n");
  503.         fprintf(ft, "\txref\t%s\n\n", base);
  504.  
  505.         fprintf(ft, "\txdef\t%s\n", FuncName);
  506.         fprintf(ft, "%s:\n", FuncName);
  507.  
  508.         AddLVOList(funcName, -bias);
  509.  
  510.         if (ProfOpt) {
  511.         fprintf(ft, "\tjsr\t__ProfExec%s\n", CodeModel);
  512.         fprintf(ft, "lp1\n");
  513.         }
  514.  
  515.         if (RegOpt == 0 || rs->rn_Args == -1) {    /*  STACK CALL */
  516.         StackCall(ft, base, bias, FRegs, argCnt);
  517.         } else {                    /*  REG CALL   */
  518.         RegsCall(ft, base, bias, rs, FRegs);
  519.         }
  520.         fputs("\tEND\n", ft);
  521.         fclose(ft);
  522.  
  523.         /*
  524.          *    assemble the temp file
  525.          */
  526.  
  527.         if (Verbose)
  528.         puts("");
  529.         if (AssembleFile(tmpFile, objFile))
  530.         JoinOutput(fo, objFile);
  531.         remove(objFile);
  532.         remove(tmpFile);
  533.     } else {
  534.         printf("\tError, Unable to create file: %s\n", tmpFile);
  535.     }
  536.     }
  537. }
  538.  
  539. void
  540. ScanRSTmp(fi)
  541. FILE *fi;
  542. {
  543.     RSNode *rs;
  544.     char *ptr;
  545.     char *symPtr;
  546.  
  547.     while (fgets(Buf, sizeof(Buf), fi)) {
  548.     if (strnicmp(Buf, "##regspec", 9) != 0)
  549.         continue;
  550.  
  551.     for (ptr = Buf + 9; *ptr == ' ' || *ptr == '\t'; ++ptr);
  552.     symPtr = ptr;
  553.     while (*ptr && *ptr != '(')
  554.         ++ptr;
  555.     if (*ptr != '(') {
  556.         printf("Error scanning RS file: %s\n", Buf);
  557.         continue;
  558.     }
  559.     *ptr++ = 0;
  560.     rs = malloc(sizeof(RSNode) + strlen(symPtr) + 1);
  561.     rs->rn_Node.ln_Name = (char *)(rs + 1);
  562.     rs->rn_Flag = 0;
  563.     strcpy(rs->rn_Node.ln_Name, symPtr);
  564.  
  565.     if (*ptr == '*') {
  566.         rs->rn_Args = -1;
  567.         while (*ptr && *ptr != ')')
  568.         ++ptr;
  569.     } else {
  570.         rs->rn_Args = 0;
  571.         while (*ptr && *ptr != ')') {
  572.         switch(*ptr) {
  573.         case 'd':
  574.         case 'D':
  575.             rs->rn_Regs[rs->rn_Args++] = ptr[1] - '0';
  576.             ptr += 2;
  577.             break;
  578.         case 'a':
  579.         case 'A':
  580.             rs->rn_Regs[rs->rn_Args++] = ptr[1] - '0' + 8;
  581.             ptr += 2;
  582.             break;
  583.         default:
  584.             printf("Error, Illegal RS file register spec: %s\n", ptr);
  585.             ptr = "";
  586.             break;
  587.         }
  588.         if (*ptr == ',')
  589.             ++ptr;
  590.         }
  591.     }
  592.     if (*ptr != ')') {
  593.         printf("Error scanning RS file: %s\n", symPtr + strlen(symPtr) + 1);
  594.         continue;
  595.     }
  596.     if (Verbose > 1)
  597.         printf("RS-SCAN: %s (%d)\n", rs->rn_Node.ln_Name, rs->rn_Args);
  598.     AddTail((struct List *)&RSList, &rs->rn_Node);
  599.     }
  600. }
  601.  
  602. int
  603. AssembleFile(inFile, outFile)
  604. char *inFile;
  605. char *outFile;
  606. {
  607.     remove(outFile);
  608.  
  609.     if (Verbose > 2) {
  610.     FILE *fi;
  611.  
  612.     if ((fi = fopen(inFile, "r")) != NULL) {
  613.         while (fgets(Buf, sizeof(Buf), fi))
  614.         fputs(Buf, stdout);
  615.         fclose(fi);
  616.     }
  617.     }
  618. /*    sprintf(Buf, "%sdas %s -o %s -nu -sym", */
  619.     sprintf(Buf, "%sdas %s -o %s",
  620.     Prefix,
  621.     inFile,
  622.     outFile
  623.      );
  624.      if (Verbose > 0)
  625.      puts(Buf);
  626.      if(Symbols)strcat(Buf," -s");
  627. #ifdef unix
  628.     system(Buf);
  629. #else
  630.     Execute(Buf, NULL, NULL);
  631. #endif
  632.     return(1);
  633. }
  634.  
  635. void
  636. JoinOutput(fo, file)
  637. FILE *fo;
  638. char *file;
  639. {
  640.     FILE *fi;
  641.     short c;
  642.  
  643.     if ((fi = fopen(file, "r")) != NULL) {
  644.     while ((c = getc(fi)) != EOF)
  645.         putc(c, fo);
  646.     fclose(fi);
  647.     } else {
  648.     printf("Error, Can't read %s\n", file);
  649.     }
  650. }
  651.  
  652. /*
  653.  *  Generate assembly for a stack based call
  654.  */
  655.  
  656. void
  657. StackCall(FILE *ft, char *base, long bias, short *regs, short args)
  658. {
  659.     uword mask = (RegsToMask(regs, args) | RF_BP) & ~RF_SCRATCH;
  660.     char *ptr;
  661.     short i;
  662.     short j;
  663.     short n;
  664.  
  665.     /*
  666.      *    step 1, what regs need to be saved?
  667.      */
  668.  
  669.     n = PushMask(ft, mask);
  670.  
  671.     /*
  672.      *    step 2, load regs from stack
  673.      */
  674.  
  675.     for (i = j = 0; i < args; i = j) {
  676.     uword lmask = 1 << regs[i];
  677.     short ln;
  678.     int offset = n * 4 + i * 4 + 4;
  679.  
  680.     for (j = i + 1; j < args; ++j) {
  681.         if (regs[j] < regs[j-1])
  682.         break;
  683.         lmask |= 1 << regs[j];
  684.     }
  685.     ptr = RegMaskToStr(lmask, &ln);
  686.     if (ln > 1)
  687.         fprintf(ft, "\tmovem.l\t%d(sp),%s\n", offset, ptr);
  688.     else if (ln > 0)
  689.         fprintf(ft, "\tmove.l\t%d(sp),%s\n", offset, ptr);
  690.     }
  691.     /*
  692.      *    step 3, load library base register
  693.      */
  694.  
  695.     fprintf(ft, "\tmove.l\t%s%s,A%d\n", base, DataModel, RB_BP - 8);
  696.  
  697.     /*
  698.      *    step 4, make call & return
  699.      */
  700.  
  701.     if (n) {
  702.     fprintf(ft, "\tjsr\t-%ld(A%d)\n", bias, RB_BP - 8);
  703.     PopMask(ft, mask);
  704.     if (ProfOpt) {
  705.         fprintf(ft, "\tjsr\t__ProfExec%s\n", CodeModel);
  706.         fprintf(ft, "lp2\n");
  707.     }
  708.     fprintf(ft, "\tRTS\n");
  709.     } else {
  710.     if (ProfOpt) {
  711.         fprintf(ft, "\tjsr\t-%ld(A%d)\n", bias, RB_BP - 8);
  712.         fprintf(ft, "\tjsr\t__ProfExec%s\n", CodeModel);
  713.         fprintf(ft, "lp2\n");
  714.         fprintf(ft, "\tRTS\n");
  715.     } else {
  716.         fprintf(ft, "\tjmp\t-%ld(A%d)\n", bias, RB_BP - 8);
  717.     }
  718.     }
  719. }
  720.  
  721. /*
  722.  *  Generate assembly for a register based call
  723.  */
  724.  
  725. void
  726. RegsCall(ft, base, bias, rs, regs)
  727. FILE *ft;
  728. char *base;
  729. long bias;
  730. RSNode *rs;
  731. short *regs;
  732. {
  733.     uword mask = (RegsToMask(regs, rs->rn_Args) | RF_BP) & ~RF_SCRATCH;
  734.     short i;
  735.     short j;
  736.     short n;
  737.  
  738.     /*
  739.      *    step 1, what regs need to be saved?
  740.      */
  741.  
  742.     n = PushMask(ft, mask);
  743.  
  744.     /*
  745.      *    step 2, load regs from other regs.  If destination is 'in use',
  746.      *    then use EXG instead (and track where the reg went to)
  747.      *
  748.      *    src:    rs->rn_Regs[i]
  749.      *    dest:    regs[i]
  750.      */
  751.  
  752.     for (i = 0; i < rs->rn_Args; ++i) {
  753.     for (j = 0; j < rs->rn_Args; ++j) { /*    is dest in use? */
  754.         if (i != j && regs[i] == rs->rn_Regs[j])
  755.         break;
  756.     }
  757.     if (j == rs->rn_Args) {         /*  not in use        */
  758.         if (regs[i] != rs->rn_Regs[i]) {    /*  not in right plac    */
  759.         fprintf(ft, "\tmove.l\t%s,%s\n", RegToStr(rs->rn_Regs[i]), RegToStr(regs[i]));
  760.         rs->rn_Regs[i] = -1;
  761.         }
  762.     } else {
  763.         fprintf(ft, "\texg.l\t%s,%s\n", RegToStr(rs->rn_Regs[i]), RegToStr(regs[i]));
  764.         rs->rn_Regs[j] = rs->rn_Regs[i];
  765.         rs->rn_Regs[i] = -1;
  766.     }
  767.     }
  768.  
  769.     /*
  770.      *    step 3, load library base register
  771.      */
  772.  
  773.     fprintf(ft, "\tmove.l\t%s%s,A%d\n", base, DataModel, RB_BP - 8);
  774.  
  775.     /*
  776.      *    step 4, make call and return
  777.      */
  778.  
  779.     if (n) {
  780.     fprintf(ft, "\tjsr\t-%ld(A%d)\n", bias, RB_BP - 8);
  781.     PopMask(ft, mask);
  782.  
  783.     if (ProfOpt) {
  784.         fprintf(ft, "\tjsr\t__ProfExec%s\n", CodeModel);
  785.         fprintf(ft, "lp2\n");
  786.     }
  787.     fprintf(ft, "\tRTS\n");
  788.     } else {
  789.     if (ProfOpt) {
  790.         fprintf(ft, "\tjsr\t-%ld(A%d)\n", bias, RB_BP - 8);
  791.         fprintf(ft, "\tjsr\t__ProfExec%s\n", CodeModel);
  792.         fprintf(ft, "lp2\n");
  793.         fprintf(ft, "\tRTS\n");
  794.     } else {
  795.         fprintf(ft, "\tjmp\t-%ld(A%d)\n", bias, RB_BP - 8);
  796.     }
  797.     }
  798. }
  799.  
  800. char *
  801. RegMaskToStr(uword mask, short *nr)
  802. {
  803.     static char buf[64];
  804.     char *ptr = buf;
  805.     short i;
  806.     short l = -1;
  807.  
  808.     *nr = 0;
  809.  
  810.     for (i = 0; i < 8; ++i) {
  811.     if (mask & (1 << i)) {
  812.         ++*nr;
  813.         if (l >= 0)
  814.         *ptr++ = '/';
  815.         ptr += sprintf(ptr, "D%d", i);
  816.         l = i;
  817.     }
  818.     }
  819.     for (i = 8; i < 16; ++i) {
  820.     if (mask & (1 << i)) {
  821.         ++*nr;
  822.         if (l >= 0)
  823.         *ptr++ = '/';
  824.         ptr += sprintf(ptr, "A%d", i - 8);
  825.         l = i;
  826.     }
  827.     }
  828.     *ptr = 0;
  829.     return(buf);
  830. }
  831.  
  832. uword
  833. RegsToMask(short *regs, short args)
  834. {
  835.     uword mask = 0;
  836.  
  837.     while (args > 0) {
  838.     mask |= 1 << *regs++;
  839.     --args;
  840.     }
  841.     return(mask);
  842. }
  843.  
  844. char *
  845. RegToStr(short rno)
  846. {
  847.     static char Buf[2][16];
  848.     static short BNo;
  849.     char *ptr = Buf[BNo];
  850.  
  851.     BNo = 1 - BNo;
  852.     if (rno < 8)
  853.     sprintf(ptr, "D%d", rno);
  854.     else
  855.     sprintf(ptr, "A%d", rno - 8);
  856.     return(ptr);
  857. }
  858.  
  859. short
  860. PushMask(FILE *fo, uword mask)
  861. {
  862.     short n;
  863.     char *ptr;
  864.  
  865.     ptr = RegMaskToStr(mask, &n);
  866.     if (n > 1)
  867.     fprintf(fo, "\tmovem.l\t%s,-(sp)\n", ptr);
  868.     else if (n > 0)
  869.     fprintf(fo, "\tmove.l\t%s,-(sp)\n", ptr);
  870.     return(n);
  871. }
  872.  
  873. short
  874. PopMask(FILE *fo, uword mask)
  875. {
  876.     short n;
  877.     char *ptr;
  878.  
  879.     ptr = RegMaskToStr(mask, &n);
  880.     if (n > 1)
  881.     fprintf(fo, "\tmovem.l\t(sp)+,%s\n", ptr);
  882.     else if (n > 0)
  883.     fprintf(fo, "\tmove.l\t(sp)+,%s\n", ptr);
  884.     return(n);
  885. }
  886.  
  887. void
  888. AddLVOList(funcName, bias)
  889. char *funcName;
  890. int bias;
  891. {
  892.     LVONode *node;
  893.  
  894.     if ((node = malloc(sizeof(LVONode) + strlen(funcName) + 1)) != NULL) {
  895.     AddTail(&LVOList, &node->lv_Node);
  896.     node->lv_Node.ln_Name = (char *)(node + 1);
  897.     strcpy(node->lv_Node.ln_Name, funcName);
  898.     node->lv_Offset = bias;
  899.     }
  900. }
  901.  
  902. void
  903. GenerateLVOList(fo)
  904. FILE *fo;
  905. {
  906.     char tmpFile[L_tmpnam];
  907.     char objFile[L_tmpnam + 4];
  908.     LVONode *node;
  909.     FILE *ft;
  910.  
  911.     tmpnam(tmpFile);
  912.     sprintf(objFile, "%s.o", tmpFile);
  913.  
  914.     if ((node = (LVONode *)RemHead((struct List *)&LVOList)) != NULL) {
  915.     if ((ft = fopen(tmpFile, "w")) != NULL) {
  916.         fprintf(ft, "\n\tsection ,code\n\n");
  917.  
  918.         while (node) {
  919.         if (Verbose)
  920.             printf("_LVO%-20s = %d\n", node->lv_Node.ln_Name, node->lv_Offset);
  921.         fprintf(ft, "_LVO%s\tEQU\t%d\n", node->lv_Node.ln_Name, node->lv_Offset);
  922.         fprintf(ft, "\txdef\t_LVO%s\n", node->lv_Node.ln_Name);
  923.         free(node);
  924.         node = (LVONode *)RemHead((struct List *)&LVOList);
  925.         }
  926.         fputs("\tEND\n", ft);
  927.         fclose(ft);
  928.  
  929.         if (AssembleFile(tmpFile, objFile))
  930.         JoinOutput(fo, objFile);
  931.         remove(objFile);
  932.         remove(tmpFile);
  933.     }
  934.     }
  935. }
  936.  
  937. /*
  938.  *  generate auto-open tag code for this library
  939.  */
  940.  
  941. void
  942. GenerateAutoOpen(fo, base)
  943. FILE *fo;
  944. char *base;
  945. {
  946.     char tmpFile[L_tmpnam];
  947.     char objFile[L_tmpnam + 4];
  948.     FILE *ft;
  949.  
  950.     tmpnam(tmpFile);
  951.     sprintf(objFile, "%s.o", tmpFile);
  952.  
  953.     if ((ft = fopen(tmpFile, "w")) != NULL) {
  954.     fprintf(ft, "\n\txdef\t%s\n", base);
  955.     fprintf(ft, "\n\txref\t__AutoFail0\n\n");
  956.     fprintf(ft, "_LVOOpenLibrary\tequ\t-552\n");
  957.     fprintf(ft, "_LVOCloseLibrary\tequ\t-414\n\n");
  958.  
  959.     fprintf(ft, "\n\tsection autoinit0,code\n\n");
  960.  
  961.     fprintf(ft, "\tmoveq.l\t#0,D0\n");
  962.     fprintf(ft, "\tlea\tlibname(pc),A1\n");
  963.     fprintf(ft, "\tjsr\t_LVOOpenLibrary(A6)\n");
  964.     fprintf(ft, "\tmove.l\tD0,%s%s\n", base, DataModel);
  965.     fprintf(ft, "\tbeq\t__AutoFail0\n");
  966.     fprintf(ft, "\tbra\topennext\n");
  967.     fprintf(ft, "libname\tdc.b\t'%s',0\n", SharedLibName);
  968.     fprintf(ft, "\tds.w\t0\n");
  969.     fprintf(ft, "opennext\n\n");
  970.  
  971.     fprintf(ft, "\tsection autoexit0,code\n\n");
  972.     fprintf(ft, "\tmove.l\t%s%s,D0\n", base, DataModel);
  973.     fprintf(ft, "\tbeq\tclosenext\n");
  974.     fprintf(ft, "\tmove.l\tD0,A1\n");
  975.     fprintf(ft, "\tjsr\t_LVOCloseLibrary(A6)\n");
  976.     fprintf(ft, "closenext\n\n");
  977.  
  978.     fprintf(ft, "\tsection libdata,data\n\n");
  979.     fprintf(ft, "%s\tdc.l\t0\n", base);
  980.  
  981.     fputs("\tEND\n", ft);
  982.     fclose(ft);
  983.  
  984.     if (AssembleFile(tmpFile, objFile))
  985.         JoinOutput(fo, objFile);
  986.     remove(objFile);
  987.     remove(tmpFile);
  988.     }
  989. }
  990.  
  991.  
  992. #ifdef LATTICE
  993.  
  994. char *
  995. tmpnam(buf)
  996. char *buf;
  997. {
  998.     static char Buf[L_tmpnam];
  999.     static short Seq;
  1000.  
  1001.     if (buf == NULL)
  1002.     buf = Buf;
  1003.     sprintf(buf, "T:%06lx%d", (long)FindTask(NULL) >> 4, Seq++);
  1004.     return(buf);
  1005. }
  1006.  
  1007. #endif
  1008.  
  1009. void
  1010. DicePrefix(char *buf, char *av0, char *app)
  1011. {
  1012.     char *ptr;
  1013.     short n = 0;
  1014.  
  1015.     for (ptr=av0+strlen(av0); ptr >= av0 && *ptr != '/' && *ptr != ':'; --ptr)
  1016.     ;
  1017.     ++ptr;
  1018.     if ((av0 = strchr(ptr, '_')) != NULL) {
  1019.     n = av0 - ptr + 1;
  1020.     strncpy(buf, ptr, n);
  1021.     }
  1022.     strcpy(buf + n, app);
  1023. }
  1024.  
  1025.